package tc.de.krawallmann.extension;

import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import tc.de.krawallmann.achievement.Achievement;
import tc.de.krawallmann.achievement.AchievementsListener;
import tc.de.krawallmann.persistence.XMLStorage;

/**
 * The Class AchievementExtension manages Achievements
 * @author KrawallMann
 * @version 1.0
 */
public class AchievementExtension implements PersistenceExtension {
	
	/** The achievements. */
	private transient Map<String, Achievement> achievements;
	
	/** The achievements file. */
	private transient final String achievementsFile;
	
	/** The ach listeners. */
	private transient final Set<AchievementsListener> achListeners =
			new HashSet<AchievementsListener>();

	/**
	 * Instantiates a new AchievementExtension.
	 * 
	 * @param inputFile
	 *            the input file
	 */
	public AchievementExtension(final String inputFile) {
		super();
		if (inputFile == null) {
			throw new IllegalArgumentException("Achievement file is null!");
		}
		achievementsFile = inputFile;
	}

	/**
	 * Adds the AchievementsListener.
	 * 
	 * @param listener
	 *            the listener
	 * @return true, if successful
	 */
	public boolean addAchievementsListener(final AchievementsListener listener) {
		return achListeners.add(listener);
	}

	/**
	 * Clear all AchievementsListeners.
	 */
	public void clearAchievementsListener() {
		achListeners.clear();
	}

	/**
	 * Contains AchievementsListener?
	 * 
	 * @param listener
	 *            the listener
	 * @return true, if successful
	 */
	public boolean containsAchievementsListener(final AchievementsListener listener) {
		return achListeners.contains(listener);
	}

	/**
	 * Gets the Achievements.
	 * 
	 * @return the Achievements
	 */
	public Collection<Achievement> getAchievements() {
		return achievements.values();
	}

	/* (non-Javadoc)
	 * @see tc.de.krawallmann.extension.Extension#init()
	 */
	@Override
	public void init() {
		// Empty!
	}

	/**
	 * Checks if the given Achievement is unlocked.
	 * 
	 * @param achievement
	 *            the Achievement
	 * @return true, if is unlocked
	 */
	public boolean isUnlocked(final Achievement achievement) {
		return achievements.containsKey(achievement.getGame() + "/"
				+ achievement.getInternalString());
	}

	/* (non-Javadoc)
	 * @see tc.de.krawallmann.extension.PersistenceExtension#read()
	 */
	@Override
	public boolean read() {
		try {
			achievements = XMLStorage.deserialize(achievements, achievementsFile);
			return true;
		} catch (final Exception e) {
			achievements = new HashMap<String, Achievement>();
			return false;
		}
	}

	/**
	 * Removes the AchievementsListener.
	 * 
	 * @param listener
	 *            the listener
	 * @return true, if successful
	 */
	public boolean removeAchievementsListener(final AchievementsListener listener) {
		return achListeners.remove(listener);
	}

	/* (non-Javadoc)
	 * @see tc.de.krawallmann.extension.PersistenceExtension#store()
	 */
	@Override
	public boolean store() {
		try {
			XMLStorage.store(achievements, achievementsFile);
			return true;
		} catch (final Exception e) {
			return false;
		}
	}

	/**
	 * Unlock an Achievement.
	 * 
	 * @param achievement
	 *            the Achievement
	 */
	public void unlockAchievement(final Achievement achievement) {
		if (!achievements
				.containsKey(achievement.getGame() + "/" + achievement.getInternalString())) {
			achievements.put(achievement.getGame() + "/" + achievement.getInternalString(),
					achievement);
			for (final AchievementsListener l : achListeners) {
				l.achievementUnlocked(achievement);
			}
		}
	}

	/* (non-Javadoc)
	 * @see tc.de.krawallmann.extension.Extension#update(long)
	 */
	@Override
	public void update(final long delta) {
		// Empty!
	}
}
